package fosu.generated.service.impl;

import fosu.generated.dto.DetectionResultDTO;
import fosu.generated.entity.Paper;
import fosu.generated.entity.Paragraph;
import fosu.generated.mapper.PaperMapper;
import fosu.generated.mapper.ParagraphMapper;
import fosu.generated.service.DetectionService;
import fosu.generated.service.PaperService;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.text.PDFTextStripper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * 论文服务实现类
 */
@Service
public class PaperServiceImpl implements PaperService {

    private static final Logger logger = LoggerFactory.getLogger(PaperServiceImpl.class);

    @Autowired
    private PaperMapper paperMapper;

    @Autowired
    private ParagraphMapper paragraphMapper;

    @Autowired
    private DetectionService detectionService;

    private static final String UPLOAD_DIR = "uploads";

    @Override
    public Paper uploadPaper(MultipartFile file, Long userId) throws IOException {
        logger.info("开始上传论文，用户ID: {}, 文件名: {}", userId, file.getOriginalFilename());

        try {
            // 创建上传目录
            Path uploadPath = Paths.get(UPLOAD_DIR);
            if (!Files.exists(uploadPath)) {
                Files.createDirectories(uploadPath);
                logger.debug("创建上传目录: {}", uploadPath);
            }

            // 保存文件
            String fileName = UUID.randomUUID().toString() + "_" + file.getOriginalFilename();
            Path filePath = uploadPath.resolve(fileName);
            Files.copy(file.getInputStream(), filePath);
            logger.info("文件保存成功: {}", filePath);

            // 解析文件内容
            String content = extractText(file);
            List<String> paragraphs = splitParagraphs(content);
            logger.info("解析完成，共 {} 个段落", paragraphs.size());

            // 保存论文信息
            Paper paper = new Paper();
            paper.setUserId(userId);
            paper.setTitle(file.getOriginalFilename());
            paper.setFilePath(filePath.toString());
            paper.setFileSize(file.getSize());
            paper.setTotalParagraphs(paragraphs.size());
            paper.setStatus("待检测");
            paper.setCreateTime(LocalDateTime.now());

            paperMapper.insert(paper);
            logger.info("论文信息保存成功，论文ID: {}", paper.getId());

            // 保存段落
            List<Paragraph> paragraphList = new ArrayList<>();
            for (int i = 0; i < paragraphs.size(); i++) {
                Paragraph paragraph = new Paragraph();
                paragraph.setPaperId(paper.getId());
                paragraph.setParagraphIndex(i);
                paragraph.setContent(paragraphs.get(i));
                paragraph.setAiProbability(0.0);
                paragraph.setRiskLevel("LOW");
                paragraph.setIsRewritten(false);
                paragraph.setCreateTime(LocalDateTime.now());
                paragraphList.add(paragraph);
            }
            paragraphMapper.insertBatch(paragraphList);
            logger.info("段落信息保存成功，共 {} 个段落", paragraphList.size());

            return paper;

        } catch (Exception e) {
            logger.error("上传论文失败", e);
            throw e;
        }
    }

    /**
     * 提取文本内容
     */
    private String extractText(MultipartFile file) throws IOException {
        String filename = file.getOriginalFilename();
        if (filename != null && filename.toLowerCase().endsWith(".pdf")) {
            return extractTextFromPDF(file);
        } else {
            return new String(file.getBytes());
        }
    }

    /**
     * 从PDF提取文本
     */
    private String extractTextFromPDF(MultipartFile file) throws IOException {
        try (PDDocument document = PDDocument.load(file.getInputStream())) {
            PDFTextStripper stripper = new PDFTextStripper();
            return stripper.getText(document);
        }
    }

    /**
     * 分割段落
     */
    private List<String> splitParagraphs(String content) {
        String[] splits = content.split("\n\n");
        List<String> paragraphs = new ArrayList<>();
        for (String split : splits) {
            String trimmed = split.trim();
            if (trimmed.length() > 10) { // 过滤太短的段落
                paragraphs.add(trimmed);
            }
        }
        return paragraphs;
    }

    @Override
    public DetectionResultDTO detectPaper(Long paperId) {
        logger.info("开始检测论文，论文ID: {}", paperId);

        try {
            Paper paper = paperMapper.findById(paperId);
            List<Paragraph> paragraphs = paragraphMapper.findByPaperId(paperId);

            logger.info("论文 {} 共有 {} 个段落需要检测", paperId, paragraphs.size());

            // 调用检测服务
            for (Paragraph paragraph : paragraphs) {
                double probability = detectionService.detectAIProbability(paragraph.getContent());
                paragraph.setAiProbability(probability);
                paragraph.setRiskLevel(getRiskLevel(probability));
                paragraphMapper.update(paragraph);
            }

            paper.setStatus("已完成");
            paperMapper.update(paper);

            logger.info("论文检测完成，论文ID: {}", paperId);

            DetectionResultDTO result = new DetectionResultDTO();
            result.setParagraphs(convertToDTO(paragraphs));
            return result;

        } catch (Exception e) {
            logger.error("检测论文失败，论文ID: {}", paperId, e);
            throw e;
        }
    }

    @Override
    public DetectionResultDTO rewriteParagraph(Long paperId, Long paragraphId) {
        logger.info("开始改写段落，论文ID: {}, 段落ID: {}", paperId, paragraphId);

        try {
            if (paragraphId == -1) {
                // 整篇改写
                List<Paragraph> paragraphs = paragraphMapper.findByPaperId(paperId);
                for (Paragraph paragraph : paragraphs) {
                    if (paragraph.getAiProbability() > 60) {
                        String rewritten = detectionService.rewriteParagraph(
                                paragraph.getContent(),
                                paragraph.getAiProbability()
                        );
                        paragraph.setContent(rewritten);
                        double newProb = detectionService.detectAIProbability(rewritten);
                        paragraph.setAiProbability(newProb);
                        paragraph.setRiskLevel(getRiskLevel(newProb));
                        paragraph.setIsRewritten(true);
                        paragraphMapper.update(paragraph);
                    }
                }
                logger.info("整篇改写完成");
            } else {
                // 单段改写
                List<Paragraph> paragraphs = paragraphMapper.findByPaperId(paperId);
                Paragraph paragraph = paragraphs.stream()
                        .filter(p -> p.getId().equals(paragraphId))
                        .findFirst()
                        .orElseThrow(() -> new RuntimeException("段落不存在"));

                String rewritten = detectionService.rewriteParagraph(
                        paragraph.getContent(),
                        paragraph.getAiProbability()
                );
                double newProb = detectionService.detectAIProbability(rewritten);

                DetectionResultDTO result = new DetectionResultDTO();
                result.setRewrittenContent(rewritten);
                result.setNewProbability(newProb);
                result.setOriginalProbability(paragraph.getAiProbability());
                return result;
            }

            return new DetectionResultDTO();

        } catch (Exception e) {
            logger.error("改写段落失败", e);
            throw e;
        }
    }

    @Override
    public List<Paper> getPaperList(Long userId) {
        logger.info("获取论文列表，用户ID: {}", userId);
        return paperMapper.findByUserId(userId);
    }

    @Override
    public byte[] exportReport(Long paperId) {
        logger.info("导出报告，论文ID: {}", paperId);
        // TODO: 实现PDF报告导出
        return new byte[0];
    }

    /**
     * 获取风险等级
     */
    private String getRiskLevel(double probability) {
        if (probability <= 30) return "LOW";
        if (probability <= 60) return "MEDIUM";
        if (probability <= 90) return "HIGH";
        return "VERY_HIGH";
    }

    /**
     * 转换为DTO
     */
    private List<DetectionResultDTO.ParagraphDTO> convertToDTO(List<Paragraph> paragraphs) {
        List<DetectionResultDTO.ParagraphDTO> dtos = new ArrayList<>();
        for (Paragraph p : paragraphs) {
            DetectionResultDTO.ParagraphDTO dto = new DetectionResultDTO.ParagraphDTO();
            dto.setId(p.getId());
            dto.setContent(p.getContent());
            dto.setAiProbability(p.getAiProbability());
            dto.setRiskLevel(p.getRiskLevel());
            dtos.add(dto);
        }
        return dtos;
    }
}